package com.guoxue.action.back;

import java.io.ByteArrayInputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.guoxue.action.front.BaseAction;
import com.guoxue.domain.*;
import com.guoxue.model.BookConfig;
import com.guoxue.model.ChapterConfig;
import com.guoxue.model.ExplainConfig;
import com.guoxue.model.PlanConfig;
import com.guoxue.service.IBookConfigService;
import com.guoxue.service.IChapterConfigService;
import com.guoxue.service.IDistrictService;
import com.guoxue.service.IExpertReadingService;
import com.guoxue.service.IExplainConfigService;
import com.guoxue.service.IPlanConfigService;
import com.guoxue.service.IPropertyConfigService;
import com.guoxue.service.IPublishLogsService;
import com.guoxue.service.IRecordConfigService;
import com.guoxue.service.IStageConfigService;
import com.guoxue.service.IStoryConfigService;
import com.guoxue.service.IUpdateService;
import com.guoxue.service.IUploadLogsService;
import com.guoxue.util.ExcelUtil;
import com.guoxue.util.JsonUtil;
import com.guoxue.util.LoggerUtil;
import com.guoxue.util.MD5Util;
import com.guoxue.util.OSSUtil;
import com.guoxue.util.OtherUtils;


/**
 * 配置文件上传等相关处理
 * @author young
 *
 */
@Controller
@RequestMapping("File")
public class UploadLogsAction extends BaseAction{
	
	@Resource
	private IUploadLogsService uploadLogsService;
	@Resource
	private ExcelUtil util;
	@Resource
	private IRecordConfigService recordServcie;
	@Resource
	private IBookConfigService bookServcie;
	@Resource
	private IChapterConfigService chapterService;
	@Resource
	private IExpertReadingService expertService;
	@Resource
	private IExplainConfigService explainService;
	@Resource
	private IPlanConfigService planConfigService;
	@Resource
	private IPropertyConfigService propertyConfigService;
	@Resource
	private IDistrictService districtService;
	@Resource
	private IStageConfigService stageConfigService;
	@Resource
	private IStoryConfigService storyConfigService;
	@Resource
	private IPublishLogsService publishService;
	@Resource
	private IUpdateService updateService;
	@Resource
	private OSSUtil oss;
	//oss节点
	private final String bucket = "bykj-gx-oss-bucket1";
	/**
	 * 各配置文件上传
	 * @param req
	 * @param resp
	 * @param file
	 * @param type
	 * @return
	 */
	@RequestMapping("/upload")
	@ResponseBody
	public JSON uploadFiles(HttpServletRequest req, HttpServletResponse resp, MultipartFile file, String type){
		try {
			String fileName = file.getOriginalFilename();
			String relName = OtherUtils.UuidUtils().substring(15,31);
			//UploadLogsVo logs = new UploadLogsVo(OtherUtils.getCurrentDate(),fileName,reName,"",reName);
			UploadLogsVo logs = new UploadLogsVo();
			logs.setUploadDate(OtherUtils.getCurrentDate());
			logs.setFileName(fileName);
			logs.setRelName(relName);
			logs.setType("");
			logs.setPath(relName);			
			oss.putObject(bucket, relName, file.getInputStream());   //存放OSS
			util.init(file.getInputStream(), logs.getFileName().split("\\.")[1]);
			if (type.equals("tapesConfig")){
				List<RecordConfigVo> ls = util.bindToModels(RecordConfigVo.class, false);  //解析装换为对应bean
				for (RecordConfigVo rc:ls){
					if (rc.getWordId()<=0){
						continue;
					}
					recordServcie.saveRecordConfig(rc);
				}
			} else if (type.equals("bookConfig")){
				List<BookConfigVo> ls = util.bindToModels(BookConfigVo.class, false);
				for (BookConfigVo bc:ls){
					if (bc.getBookId()<=0){
						continue;
					}
					bookServcie.saveBookConfig(bc);
				}
			}  else if (type.equals("chapterConfig")){
				List<ChapterConfigVo> ls = util.bindToModels(ChapterConfigVo.class, false);
				for (ChapterConfigVo cc:ls){
					if (cc.getChapterId()<=0){
						continue;
					}
					chapterService.saveChapterConfig(cc);
				}
			} else if (type.equals("masterConfig")){
				List<ExpertReadingVo> ls = util.bindToModels(ExpertReadingVo.class, false);
				for (ExpertReadingVo er: ls){
					if (er.getWorkId()<=0){
						continue;
					}
					expertService.saveExpertReading(er);
					}
			} else if (type.equals("meanConfig")){
				List<ExplainConfigVo> ls = util.bindToModels(ExplainConfigVo.class, false);
				for (ExplainConfigVo ec: ls){
					if (ec.getExplainId()<=0){
						continue;
					}
					explainService.saveExplain(ec);
				} 
			} else if (type.equals("planConfig")){
				List<PlanConfigVo> ls = util.bindToModels(PlanConfigVo.class, false);
				for (PlanConfigVo pc: ls){
					if (pc.getPlanId()<=0){
						continue;
					}
					planConfigService.savePlanConfig(pc);
				}
			} else if (type.equals("propConfig")){
				List<PropertyConfigVo> ls = util.bindToModels(PropertyConfigVo.class, false);
				for (PropertyConfigVo pc: ls){
					if (pc.getPropId()<=0){
						continue;
					}
					propertyConfigService.savePropertyConfig(pc);
				}
			} else if (type.equals("regionConfig")){
				List<DistrictVo> ls = util.bindToModels(DistrictVo.class, false);
				for (DistrictVo dt: ls){
					districtService.saveDistrict(dt);
				}
			} else if (type.equals("levelConfig")){
				List<StageConfigVo> ls = util.bindToModels(StageConfigVo.class, false);
				for (StageConfigVo sc: ls){
					if (sc.getStageId()<=0){
						continue; 
					}
					stageConfigService.saveStageConfig(sc);
				}
			} else if (type.equals("storyConfig")){
				List<StoryConfigVo> ls = util.bindToModels(StoryConfigVo.class, false);
				for (StoryConfigVo sc: ls){
					if (sc.getStoryId()<=0){
						continue;
					}
					storyConfigService.saveStoryConfig(sc);
				}
			} else {
				return Message(ERROR, "所传文件类型错误", null);
			}
			logs.setType(type);
			uploadLogsService.save(logs);   //上传日志存储
			return Message(SUCCESS, "上传成功", null);
		} catch (Exception e) {
			return LoggerUtil.logInfo(e,"上传异常");
		}
	}
	/**
	 *  打包解析后数据，生成对应json文件上传OSS
	 * @param req
	 * @param resp
	 * @param pub
	 * @return
	 */
	@RequestMapping("/publish")
	@ResponseBody
	public JSON publishLogs(HttpServletRequest req, HttpServletResponse resp, PublishLogsVo pub){
		try {
			int total = 0;
			String versionCode =OtherUtils.UuidUtils();
			String userName = (String)((BackUserVo) req.getSession().getAttribute("Back_user")).getTel(); //生成相关打包信息（日志）
			pub.setPublishDate(OtherUtils.getCurrentDate());
			pub.setPubUser(userName);
			pub.setVersionCode(versionCode);
			pub.setStatus("3");   //设置状态码 3：预更新版本
			List<BookConfigVo> books = bookServcie.getBookConfigList();    //打包文件按书为单位，依次打包上传
			if (books.isEmpty()){
				return Message(ERROR, "请检查典籍配置是否正确", null);
			} else {
				String file = null;
				String file2 = null;
				for (BookConfigVo bk:books){     //查找对应书籍
					BookConfig bookConfigs = new BookConfig(bk.getBookId(),bk.getBookName(),
							bk.getWriter(),bk.getReader(),bk.getBeginChapterId(),bk.getEndChapterId(),
							bk.getBeginPlanId(),bk.getEndPlanId());
					List<ChapterConfigVo> chapters = chapterService.getChapterConfigList(bk.getBeginChapterId(),bk.getEndChapterId());
					List<ChapterConfig> afterChap = new ArrayList<ChapterConfig>();
					List<PlanConfigVo> planConfigs = planConfigService.getPlanConfigListByPlan(bk.getBeginPlanId(),bk.getEndPlanId());
					if (planConfigs.isEmpty()){
						return Message(ERROR, "请检查典籍及计划配置是否正确", null);
					} else {
					List<PlanConfigVo>	planConfigList = new ArrayList<PlanConfigVo>();
						for(PlanConfigVo pc:planConfigs){
							PlanConfig planConfig = new PlanConfig(pc.getPlanId(), pc.getPlanName(), pc.getPlanTitle(), 
									pc.getPlanType(), pc.getCount(),pc.getBeginWordId(),
									pc.getEndWordId(),pc.getFirstMedal(),pc.getFirstExp(),pc.getMedal(),pc.getExp());
							List<RecordConfigVo> rc = recordServcie.getRecordConfigList(pc.getBeginWordId(), pc.getEndWordId());
							List<ExplainConfigVo> ec = explainService.getExplainConfigList(rc.get(0).getExplainId(), rc.get(rc.size()-1).getExplainId());//配置文件读取位置调整 
							try {
								ec = ExplainUtil(ec);
							} catch (Exception e) {
								return LoggerUtil.logInfo(e,"计划分词失败");
							}
							planConfig.setExplains(ec);
						    planConfig.setSentence(rc);
						    planConfigList.add(planConfig);
						}
						bookConfigs.setPlanConfigs(planConfigList);
					}
					if (chapters.isEmpty()){
						return Message(ERROR, "请检查章节配置是否正确", null);
					} else {
						List<RecordConfigVo> records = null;
						List<ExplainConfigVo> explain = null;
						List<ExplainConfig> explains = null;
						for (ChapterConfigVo cc:chapters){  //查找对应章节
							ChapterConfig chapter = new ChapterConfig(cc.getChapterId(),cc.getChapterName()
									,cc.getBeginWordId(),cc.getEndWordId());
							 records = recordServcie.getRecordConfigList(cc.getBeginWordId(),cc.getEndWordId());
							if (!records.isEmpty()){    //对应录音配置
								int begin,end = 0;
								try {
									begin = records.get(0).getExplainId();
									end = records.get(records.size()-1).getExplainId();
								} catch (Exception e) {
									return LoggerUtil.logInfo(e,"请检查录音配置是否符合格式");
								}
								explain = explainService.getExplainConfigList(begin,end); //对应释义配置
								explains = new ArrayList<ExplainConfig>();
								if (!explain.isEmpty()){
									for (ExplainConfigVo ec:explain){ 
										ExplainConfig expc = new ExplainConfig(ec.getExplainId(),ec.getWord()
												,ec.getPhoneticize(),ec.getStoryId1(),ec.getStoryId2(),
												ec.getStoryId3(),ec.getStoryId4(),ec.getWordExplain());
										List<String> words = new ArrayList<String>();
										List<String> phoneticizes = new ArrayList<String>();
										try {
											Collections.addAll(words, ec.getWord().split("_"));
											Collections.addAll(phoneticizes, ec.getPhoneticize().split("_"));
										} catch (Exception e) {
											return LoggerUtil.logInfo(e,"请释义配置是否符合格式");
										}
										expc.setPhoneticizes(phoneticizes);
										expc.setWords(words);
										List<StoryConfigVo> storys = new ArrayList<StoryConfigVo>();  //对应故事
										if(ec.getStoryId1()!=0){
											StoryConfigVo story1 = storyConfigService.getStory(ec.getStoryId1()); 
											if (story1==null){
												return Message(ERROR, "请检查故事配置", null);
											}
											storys.add(story1);
											if (ec.getStoryId2()!=0){
												StoryConfigVo story2 = storyConfigService.getStory(ec.getStoryId2());
												if (story2==null){
													return Message(ERROR, "请检查故事配置", null);
												}
												storys.add(story2);
												if (ec.getStoryId3()!=0){
													StoryConfigVo story3 = storyConfigService.getStory(ec.getStoryId3());
													if (story3==null){
														return Message(ERROR, "请检查故事配置", null);
													}
													storys.add(story3);
													if (ec.getStoryId4()!=0){
														StoryConfigVo story4 = storyConfigService.getStory(ec.getStoryId4());
														if (story4==null){
															return Message(ERROR, "请检查故事配置", null);
														}
														storys.add(story4);
													}
												}
											}
										}
										expc.setStorys(storys);
										explains.add(expc);
									}
								} else {
									return Message(ERROR, "请检释义及录音配置是否关联正确", null);
								}
							} else {
								return Message(ERROR, "请检录音及章节配置是否关联正确", null);
							}
							chapter.setExplain(explains);
							chapter.setSentence(records);
							afterChap.add(chapter);
							file = records.get(1).getFile();
							file2 = records.get(1).getFile2();
						}
					}
					bookConfigs.setChapters(afterChap);
					String key = OtherUtils.UuidUtils().substring(15,31);
					UpdateTableVo update = null;
					ByteArrayInputStream newFile = null;
					try {          
						//指定版本号上传OSS,同时查询上个版本书籍文本是否有所变动，无变动则不做更新
						PublishLogsVo pl = publishService.getPublishByStatus("4");//状态码为4 的上个版本
						newFile =  new ByteArrayInputStream(JSON.toJSONString(bookConfigs,SerializerFeature.WriteMapNullValue).getBytes());
						if (pl!=null){
							UpdateTableVo ut = updateService.getUpdateTableByVersionCodeAndBookName(pl.getVersionCode(), bk.getBookName());//按版本号及书名获取对应上个版本书籍信息
							String oldFile = oss.getInputStream(bucket,ut.getKeyAndType());//下载oss存放的上个版本书籍文本
							if(MD5Util.valid(JSON.toJSONString(bookConfigs,SerializerFeature.WriteMapNullValue), oldFile)){//MDS验证文本内容一致性
								//update = new UpdateTable(OtherUtils.UuidUtils(),bk.getBookId(),ut.getKeyAndType(),bk.getBookName(),file2,file,versionCode,ut.getSize());
								update = new UpdateTableVo();
								update.setBookId(bk.getBookId());
								update.setBookName(bk.getBookName());
								update.setKeyAndType(ut.getKeyAndType());
								update.setFileKey(file);
								update.setFileKey2(file2);
								update.setVersionCode(versionCode);
								update.setSize(ut.getSize());
							} else {
								int size = newFile.available()/1024;
//								update = new UpdateTable(OtherUtils.UuidUtils(),bk.getBookId(),key+".json",bk.getBookName(),file2,file,versionCode,size);
								update = new UpdateTableVo();
								update.setBookId(bk.getBookId());
								update.setBookName(bk.getBookName());
								update.setKeyAndType(key+".json");
								update.setFileKey(file);
								update.setFileKey2(file2);
								update.setVersionCode(versionCode);
								update.setSize(size);
								total =total+size;
								oss.putObject(bucket, key+".json",newFile);
							}
						} else {
							int size = newFile.available()/1024;
//							update = new UpdateTable(OtherUtils.UuidUtils(),bk.getBookId(),key+".json",bk.getBookName(),file2,file,versionCode,size);
							update = new UpdateTableVo();
							update.setBookId(bk.getBookId());
							update.setBookName(bk.getBookName());
							update.setKeyAndType(key+".json");
							update.setFileKey(file);
							update.setFileKey2(file2);
							update.setVersionCode(versionCode);
							update.setSize(size);
							total =total+size;
							oss.putObject(bucket, key+".json",newFile);
						}
					} catch (Exception e) {
						return LoggerUtil.logInfo(e,"提交云存储失败");
					}finally {
						newFile.close();
					}
					updateService.saveUpdate(update); //记录相关操作日志
				}
				pub.setSize(total);
				publishService.savePublishLogs(pub);
				return Message(SUCCESS, "打包成功", null);
			}
		} catch (Exception e) {
			return LoggerUtil.logInfo(e,"打包失败");
		}
	}
	//分词，查找对应故事工具类方法
	public List<ExplainConfigVo> ExplainUtil(List<ExplainConfigVo> explain){
		List<ExplainConfigVo> explains = new ArrayList<ExplainConfigVo>();
		for (ExplainConfigVo ec:explain){  
			ExplainConfig exp = new ExplainConfig(ec.getExplainId(),ec.getWord(),ec.getPhoneticize(), 
					ec.getStoryId1(),ec.getStoryId2(), ec.getStoryId3(), ec.getStoryId4(),ec.getWordExplain());
			List<String> words = new ArrayList<String>();
			List<String> phoneticizes = new ArrayList<String>();
			Collections.addAll(words, ec.getWord().split("_"));
			Collections.addAll(phoneticizes, ec.getPhoneticize().split("_"));
			exp.setPhoneticizes(phoneticizes);
			exp.setWords(words);
			exp.setWord(null);
			exp.setPhoneticize(null);
			List<StoryConfigVo> storys = new ArrayList<StoryConfigVo>();  //对应故事
			if(ec.getStoryId1()!=0){
				StoryConfigVo story1 = storyConfigService.getStory(ec.getStoryId1());  
				storys.add(story1);
				if (ec.getStoryId2()!=0){
					StoryConfigVo story2 = storyConfigService.getStory(ec.getStoryId2());
					storys.add(story2);
					if (ec.getStoryId3()!=0){
						StoryConfigVo story3 = storyConfigService.getStory(ec.getStoryId3());
						storys.add(story3);
						if (ec.getStoryId4()!=0){
							StoryConfigVo story4 = storyConfigService.getStory(ec.getStoryId4());
							storys.add(story4);
						}
					}
				}
			}
			exp.setStorys(storys);
			explains.add(exp);
		}
		return explains;
	}
}
